/*
********************************************************************************
*
*	name : dwt delay
*	file : bsp_dwt.c
********************************************************************************
*/
#include "bsp.h"
#include "bsp_delay.h"
#include "mytype.h"
#include "framework.h"

/*******************************************************************************
* @brief  VAR
*******************************************************************************/
uint32_t dly_clk_per_us;

#define APP_TIM TMR5
#define APP_TIM_IRQn TMR5_IRQn
#define app_timer_isr TMR5_IRQHandler

/*******************************************************************************
* @brief  bsp_delay_init
* \param[in] none
* \retval: none
*******************************************************************************/
void bsp_block_dly_init(void)
{
	uint32_t apb1,apb2;
	intx_alloc();

	// 使能定时器时钟
	intx_disable();
	RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_TMR5);
	RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_TMR5);
	RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_TMR5);
	intx_enable();

	// 获取时钟值
	RCM_ReadPCLKFreq(&apb1, &apb2);

	// 配置
	APP_TIM->CTRL1 = 0;
	APP_TIM->CTRL2 = 0;

	APP_TIM->DIEN = 0;
	APP_TIM->STS = 0;

	/*1ms interrupt*/
	dly_clk_per_us = 8;
	APP_TIM->PSC = (apb1 * 2 / 1000000 / dly_clk_per_us) - 1;
	APP_TIM->AUTORLD = 0xFFFF;

	// nvic
	nvic_irq_set(APP_TIM_IRQn, 0, 0);

	APP_TIM->CTRL1_B.URSSEL = 1;
	APP_TIM->CTRL1_B.CNTEN  = 1;

	APP_TIM->DIEN = 0;
}


/*******************************************************************************
* @brief  bsp_delay_ms
* \param[in] ms delay
* \retval: none
*******************************************************************************/
void bsp_block_dly_ms(uint32_t ms)
{
	while(ms--)
	{
		bsp_block_dly_us(1000);
	}
}

/*******************************************************************************
* @brief  bsp_delay_us
*         Global variable is readonly. This function can be called in multi-task.
* \param[in] us delay
* \retval: none
*******************************************************************************/
void bsp_block_dly_us(uint32_t us)
{
    uint16_t t_cnt, t_clk_req, t_start;
 
	t_start = APP_TIM->CNT;

	t_cnt = 0;
	t_clk_req = us * dly_clk_per_us;

	while(t_cnt < t_clk_req)
	{
		t_cnt = APP_TIM->CNT - t_start;
	}
}

/*******************************************************************************
 * @brief: block_dly_check
 * @param argc 参数数量
 * @param argv 参数指针
 * @return 错误代码
 ******************************************************************************/
int block_dly_check(int argc, char *argv[])
{
	int dly = 100;
	uu16 tick_start;
	uu16 ticks;
	
	if(argc > 1)
		dly = atoi(argv[1]);
	
	rang_limit_low(dly, 10);
	
	tick_start = lib_tick16_cnt;
	
	bsp_block_dly_ms(dly);
	
	ticks = lib_tick16_cnt - tick_start;
	
	dbg_print("delay time %d ms, used ticks %d \n", dly, ticks);
	dbg_puts(SYMBOL_LINE_DOT);
	
	return 0;
}
SHELL_FUNX_EXPORT(block_dly_check, "[ms]");
